package com.zh.business.base.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zh.business.base.entity.BasicEntity;
import com.zh.business.base.exception.MsgException;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 服务抽象基类
 *
 * @param <T>
 * @author walle
 */
public abstract class BasicServiceImplAbstract<T extends BasicEntity> implements BasicServiceInterface<T> {

    public abstract Mapper<T> getMapper();

    /**
     * 根据实体中的不为null的属性进行查询
     * 只能有一个返回值，有多个结果时抛出异常，查询条件使用等号 and
     *
     * @param record
     * @return
     */
    @Override
    public T selectOne(T record) {
        return getMapper().selectOne(record);
    }

    /**
     * 根据实体中不为null的属性值进行查询，查询条件使用等号
     *
     * @param record
     * @return
     */
    @Override
    public List<T> select(T record) {
        return getMapper().select(record);
    }

    /**
     * 查询全部
     *
     * @return
     */
    @Override
    public List<T> selectAll() {
        return getMapper().selectAll();
    }

    /**
     * 根据实体类不为null的字段进行排序查询，条件全部使用=号and条件
     * 需要指定排序规则，例如 "name ase",使用数据库字段名，而非属性名
     *
     * @param record      查询条件
     * @param orderSqlStr 排序规则 （如：name ase,id desc） 注意使用的是数据库字段名称
     * @return List 列表
     */
    @Override
    public List<T> selectOrder(T record, String orderSqlStr) {
        Example example = new Example(record.getClass(), false);
        Criteria criteria = example.createCriteria();
        Map<String, String> map;
        try {
            map = BeanUtils.describe(record);
            for (Entry<String, String> entry : map.entrySet()) {
                if (StringUtils.isNotBlank(entry.getValue())) {
                    criteria.andEqualTo(entry.getKey(), entry.getValue());
                }
            }
            example.setOrderByClause(orderSqlStr);
            return getMapper().selectByExample(example);
        } catch (Exception e) {
            throw new MsgException("查询错误：" + e.getMessage());
        }
    }

    /**
     * 根据实体中不为null的属性查询总数，查询条件使用等号
     *
     * @param record
     * @return 总数结果
     */
    @Override
    public int selectCount(T record) {
        return getMapper().selectCount(record);
    }

    /**
     * 根据Example条件进行查询总数
     *
     * @param example
     * @return
     */
    public int selectCountByExample(Object example) {
        return getMapper().selectCountByExample(example);
    }

    /**
     * 根据主键字段进行查询，方法参数必须包含完整的主键属性，查询条件使用等号
     * 单个字段做主键时,可以直接写主键的值。联合主键时,key可以是实体类,也可以是Map
     *
     * @param key
     * @return
     */
    @Override
    public T selectByPrimaryKey(Object key) {
        return getMapper().selectByPrimaryKey(key);
    }

    /**
     * 根据主键字段判断是否存在。方法参数必须包含完整的主键属性，查询条件使用等号
     *
     * @param key
     * @return 是否存在
     */
    @Override
    public boolean existsWithPrimaryKey(Object key) {
        return getMapper().existsWithPrimaryKey(key);
    }

    /**
     * 保存或者更新实体中不为null的值，根据传入id主键是不是null来确认
     *
     * @param record 对象
     * @return int 影响行数
     */
    /*@Override
    public int save(T record) {
        int count;
        if (record.getId() == null) {
            count = this.insertSelective(record);
        } else {
            count = this.updateByPrimaryKeySelective(record);
        }
        return count;
    }*/

    /**
     * 保存一个实体，null的属性也会保存，不会使用数据库默认值
     *
     * @param record
     * @return int 插入行数
     */
    @Override
    public int insert(T record) {
        return getMapper().insert(record);
    }

    /**
     * 保存一个实体，null的属性不会保存，会使用数据库默认值
     *
     * @param record
     * @return int 插入行数
     */
    @Override
    public int insertSelective(T record) {
        return getMapper().insertSelective(record);
    }

    /**
     * 根据主键更新实体全部字段，null值会被更新进库
     *
     * @param record
     * @return int 更新行数
     */
    @Override
    public int updateByPrimaryKey(T record) {
        return getMapper().updateByPrimaryKey(record);
    }

    /**
     * 根据主键更新实体属性不为null的值
     *
     * @param record
     * @return int 更新行数
     */
    @Override
    public int updateByPrimaryKeySelective(T record) {
        return getMapper().updateByPrimaryKeySelective(record);
    }

    /**
     * 根据实体类不为null的字段进行删除,条件全部使用=号and条件
     *
     * @param record 对象
     * @return int 删除行数
     */
    @Override
    public int delete(T record) {
        return getMapper().delete(record);
    }

    /**
     * 根据主键字段进行删除,这里最多只会删除一条数据
     * 单个字段做主键时,可以直接写主键的值 联合主键时,key可以是实体类,也可以是Map
     *
     * @param key 主键
     * @return int 删除行数
     */
    @Override
    public int deleteByPrimaryKey(Object key) {
        return getMapper().deleteByPrimaryKey(key);
    }

    /**
     * 单表分页不可排序
     *
     * @param pageNum  页码，1开始
     * @param pageSize 每页显示数量
     * @param record   对象
     * @return PageInfo 分页对象
     */
    @Override
    public PageInfo<T> selectPage(int pageNum, int pageSize, T record) {
        PageHelper.startPage(pageNum, pageSize);
        return new PageInfo<>(getMapper().select(record));
    }

    /**
     * 单表分页可排序
     *
     * @param pageNum     页码，1开始
     * @param pageSize    每页显示数量
     * @param record      对象
     * @param orderSqlStr 排序规则 (如:id desc) 注意使用的是数据库字段名称
     * @return PageInfo 分页对象
     */
    //@Override
    //public PageInfo<T> selectPageOrder(int pageNum, int pageSize, T record, String orderSqlStr) {
    //    Example example = new Example(record.getClass(), false);
    //    Criteria criteria = example.createCriteria();
    //    Map<String, String> map;
    //    try {
    //        map = PropertyUtils.describe(record);
    //        for (Entry<String, String> entry : map.entrySet()) {
    //            if (StringUtils.isNotBlank(entry.getValue())) {
    //                criteria.andEqualTo(entry.getKey(), entry.getValue());
    //            }
    //        }
    //        example.setOrderByClause(orderSqlStr);
    //        PageHelper.startPage(pageNum, pageSize);
    //        List<T> list = getMapper().selectByExample(example);
    //        return new PageInfo<>(list);
    //    } catch (Exception e) {
    //        throw new MsgException("查询错误:" + e.getMessage());
    //    }
    //}

}
